const reqlib = require('app-root-path').require
const macdUtil = reqlib('/app/util/macdUtil')
const numberUtil = reqlib('/app/util/numberUtil')
const moment = require('moment')

function getMaxDiff (list) {
  list.sort((a, b) => {
    return a - b
  })
  return Math.abs(numberUtil.countDifferenceRate(list[0], list[list.length - 1]))
}

function getItemInfo (klineList) {
  const klineListR = [...klineList]
  klineListR.reverse()
  // kdj
  const kdjList = macdUtil.getKdj(klineList)
  const kdj = {
    K: kdjList['K'][kdjList['K'].length - 1],
    D: kdjList['D'][kdjList['D'].length - 1],
    J: kdjList['J'][kdjList['J'].length - 1]
  }
  // macd
  const macdList = macdUtil.macd_data(klineList)
  macdList.forEach((v, index) => {
    macdList[index] = v / 2
  })
  // ema
  let closeList = klineList.map((v) => {
    return v.close
  })
  const ema5 = macdUtil.getEma(closeList, 5)
  const ema10 = macdUtil.getEma(closeList, 10)
  const ema20 = macdUtil.getEma(closeList, 20)
  const ema60 = macdUtil.getEma(closeList, 60)
  const diffRateMonth = numberUtil.countDifferenceRate(ema5, ema10)
  const diffRate1020 = numberUtil.countDifferenceRate(ema10, ema20)
  const diff510 = numberUtil.countDifferenceRate(ema5, ema10)
  const diff520 = numberUtil.countDifferenceRate(ema5, ema20)
  const sg = (Math.abs(diff510) + Math.abs(diff520)) / 2
  // kline
  const today = klineList[klineList.length - 1]
  return {
    kdj,
    macd: macdList[macdList.length - 1],
    ema5,
    ema10,
    ema20,
    ema60,
    kline: {
      ...today
    },
    ...today,
    diffRateMonth,
    dateTime: moment(today.time).format('YYYY-MM-DD HH:mm:ss'),
    emaMaxDiff: getMaxDiff([
      ema5,
      ema10,
      ema20
    ]),
    drab1020: Math.abs(diffRate1020),
    sg: sg
  }
}

exports.getItemInfoList = function (klineList) {
  // 从远到近
  const list = []
  // 产生60天的数据，并且一天的数据需要结合前面120天来分析
  let start = klineList.length - 60 - 120
  if (start < 0) {
    start = 0
  }
  for (let i = start; i < klineList.length; i++) {
    // +1才能包含上自己
    let endIndex = i + 1
    // 要结合前面120天来分析
    let startIndex = endIndex - 120
    if (startIndex < 0) {
      startIndex = 0
    }
    // 低于九条就会报错
    // if ((endIndex - startIndex) >= 9) {
    //   // 一般情况下至少保证有40条数据
    //   const res = await getItemInfo(klineList.slice(startIndex, endIndex))
    //   list.push(res)
    // }
    const res = getItemInfo(klineList.slice(startIndex, endIndex))
    list.push(res)
  }
  list.forEach((item, index) => {
    item.tr = 0
    let kdjDiff = 0
    if (item.kdj) {
      kdjDiff = item.kdj.J - item.kdj.D
    }
    item.kdjDiff = kdjDiff
    item.diff510 = numberUtil.countDifferenceRate(item.ema5, item.ema10)
    item.diff520 = numberUtil.countDifferenceRate(item.ema5, item.ema20)
    item.diff1020 = numberUtil.countDifferenceRate(item.ema10, item.ema20)
    item.sg = (Math.abs(item.diff510) + Math.abs(item.diff520)) / 2
    item.maxNetChangeRatio = numberUtil.countDifferenceRate(item.high, item.low)
    item.realWave = Math.abs(item.netChangeRatio / item.maxNetChangeRatio)
    item.highLowRate = numberUtil.countDifferenceRate(item.high, item.low)
    item.closeLowRate = numberUtil.countDifferenceRate(item.close, item.low)
    item.lowCloseRate = numberUtil.countDifferenceRate(item.low, item.close)
    item.lowOpenRate = numberUtil.countDifferenceRate(item.low, item.open)
    item.highCloseRate = numberUtil.countDifferenceRate(item.high, item.close)
    item.highOpenRate = numberUtil.countDifferenceRate(item.high, item.open)
  })
  return list
}

function maxDiffDays (emaList, days) {
  if (emaList.length <= days) {
    return 0
  }
  let r = 0
  let last = emaList.length - 1
  for (let i = 0; i < days; i++) {
    const em = emaList[last - i]
    r += em.emaMaxDiff
  }
  return r / days
}

exports.maxDiffDays = maxDiffDays

function macdUpDays (emaList) {
  let days = 0
  let index = emaList.length - 1
  const now = emaList[index]
  let flag = 0
  if (now.macd > 0) {
    flag = 1
  }
  if (now.macd < 0) {
    flag = -1
  }
  let countIn = false
  for (let i = 0; i < index; i++) {
    const em = emaList[index - i]
    // 现在是涨的
    if (flag === 1) {
      if (em.macd > 0) {
        days++
      } else {
        return days
      }
    }
    // 现在是跌的
    if (flag === -1) {
      if (countIn) {
        if (em.macd > 0) {
          days++
        } else {
          return days
        }
      } else {
        if (em.macd > 0) {
          days++
          countIn = true
        }
      }
    }
  }
  return days
}

exports.macdUpDays = macdUpDays

function kdjUpDays (emaList) {
  let days = 0
  let index = emaList.length - 1
  const now = emaList[index]
  let flag = 0
  if (now.kdjDiff > 0) {
    flag = 1
  }
  if (now.kdjDiff < 0) {
    flag = -1
  }
  let countIn = false
  for (let i = 0; i < index; i++) {
    const em = emaList[index - i]
    // 现在是涨的
    if (flag === 1) {
      if (em.kdjDiff > 0) {
        days++
      } else {
        return days
      }
    }
    // 现在是跌的
    if (flag === -1) {
      if (countIn) {
        if (em.kdjDiff > 0) {
          days++
        } else {
          return days
        }
      } else {
        if (em.kdjDiff > 0) {
          days++
          countIn = true
        }
      }
    }
  }
  return days
}

exports.kdjUpDays = kdjUpDays

function drab1020Days (emaList) {
  let days = 0
  let index = emaList.length - 1
  for (let i = 0; i < index; i++) {
    const em = emaList[index - i]
    if (em.drab1020 > 0.6) {
      days++
    } else {
      return days
    }
  }
  return days
}

exports.drab1020Days = drab1020Days

function countFen (em) {
  if (em.drab1020Days > 10 || em.drab1020 > 1.8) {
    return 1.32
  }
  if (em.drab1020 > 1.2 && em.drab1020 <= 1.8) {
    return 0.99
  }
  if (em.drab1020 > 0.6 && em.drab1020 <= 1.2) {
    return 0.66
  }
  if (em.drab1020 <= 0.6) {
    return 0.33
  }
}

exports.countFen = countFen

function countFenM (em) {
  if (em.drab1020Days > 10 || em.drab1020 > 1.8) {
    return 1.32
  }
  if (em.drab1020 > 1.2 && em.drab1020 <= 1.8) {
    return 0.99
  }
  if (em.drab1020 > 0.6 && em.drab1020 <= 1.2) {
    return 0.66
  }
  if (em.drab1020 <= 0.6) {
    return 0.33
  }
}

exports.countFenM = countFenM

function macdDownDays (emaList) {
  let days = 0
  let index = emaList.length - 1
  // 判断今天是涨还是跌
  const now = emaList[index]
  let flag = 0
  if (now.macd > 0) {
    flag = 1
  }
  if (now.macd < 0) {
    flag = -1
  }
  let countIn = false
  for (let i = 0; i < index; i++) {
    const em = emaList[index - i]
    // 现在是跌的
    if (flag === -1) {
      if (em.macd < 0) {
        days++
      } else {
        return days
      }
    }
    // 现在是涨的
    if (flag === 1) {
      if (countIn) {
        if (em.macd < 0) {
          days++
        } else {
          return days
        }
      } else {
        if (em.macd < 0) {
          days++
          countIn = true
        }
      }
    }
  }
  return days
}

exports.macdDownDays = macdDownDays

function kdjDownDays (emaList) {
  let days = 0
  let index = emaList.length - 1
  // 判断今天是涨还是跌
  const now = emaList[index]
  let flag = 0
  if (now.kdjDiff > 0) {
    flag = 1
  }
  if (now.kdjDiff < 0) {
    flag = -1
  }
  let countIn = false
  for (let i = 0; i < index; i++) {
    const em = emaList[index - i]
    // 现在是跌的
    if (flag === -1) {
      if (em.kdjDiff < 0) {
        days++
      } else {
        return days
      }
    }
    // 现在是涨的
    if (flag === 1) {
      if (countIn) {
        if (em.kdjDiff < 0) {
          days++
        } else {
          return days
        }
      } else {
        if (em.kdjDiff < 0) {
          days++
          countIn = true
        }
      }
    }
  }
  return days
}

exports.kdjDownDays = kdjDownDays

// macd持续时间
function macdKeepDays (emaList) {
  let days = 0
  const newList = [...emaList]
  newList.reverse()
  const now = newList[0]
  let flag = 0
  if (now.macd > 0) {
    flag = 1
  }
  if (now.macd < 0) {
    flag = -1
  }
  for (let i = 0; i < newList.length; i++) {
    const em = newList[i]
    // 现在是跌的
    if (flag === -1) {
      if (em.macd < 0) {
        days++
      } else {
        return days
      }
    }
    // 现在是涨的
    if (flag === 1) {
      if (em.macd > 0) {
        days++
      } else {
        return days
      }
    }
  }
  return days
}

exports.macdKeepDays = macdKeepDays

// 一波macd涨了多少
function macdUpVal (emaList) {
  let end = 0
  let start = 0
  let index = emaList.length - 1
  const now = emaList[index]
  if (now.macd > 0) {
    return 0
  }
  if (emaList[index - 1].macd < 0) {
    index = index - 1
    // 最多只有两天缓冲
    if (emaList[index - 2].macd < 0) {
      return 0
    }
  }
  for (let i = 1; i < index; i++) {
    const em = emaList[index - i]
    if (em.macd < 0) {
      break
    }
    if (i === 1) {
      end = em.close
    }
    start = em.open
  }
  return numberUtil.countDifferenceRate(end, start)
}

exports.macdUpVal = macdUpVal

function getEXInfo (symbols, code) {
  const codeUsdt = `${code}USDT`
  for (let i = 0; i < symbols.length; i++) {
    const symbol = symbols[i]
    if (symbol.symbol === codeUsdt) {
      let fData = {
        status: symbol.status
      }
      const filters = symbol.filters || []
      filters.forEach((v) => {
        if (v.filterType === 'LOT_SIZE') {
          fData = {
            ...fData,
            ...v
          }
        }
        if (v.filterType === 'MIN_NOTIONAL') {
          fData = {
            ...fData,
            ...v
          }
        }
        if (v.filterType === 'PRICE_FILTER') {
          fData = {
            ...fData,
            ...v
          }
        }
      })
      return fData
    }
  }
  return {}
}

exports.getEXInfo = getEXInfo

function getAstItem (list, code) {
  for (let i = 0; i < list.length; i++) {
    if (list[i].symbol === `${code}USDT`) {
      return list[i]
    }
  }
  return false
}

exports.getAstItem = getAstItem

function ifMacdUpTimes (list, times, diff) {
  const newList = [...list]
  // 近的在前了
  newList.reverse()
  let days = 0
  if (
    (newList[0] && newList[0].macd > 0) &&
    (newList[times - 1] && newList[times - 1].macd > 0)
  ) {
    for (let i = 0; i < times; i++) {
      const em = newList[i]
      if (em.macd > 0) {
        days++
      }
    }
  }
  return days >= (times - (diff || 0))
}

exports.ifMacdUpTimes = ifMacdUpTimes

function ifMacdDownTimes (list, times, diff) {
  const newList = [...list]
  // 近的在前了
  newList.reverse()
  let days = 0
  if (
    (newList[0] && newList[0].macd < 0) &&
    (newList[times - 1] && newList[times - 1].macd < 0)
  ) {
    for (let i = 0; i < times; i++) {
      const em = newList[i]
      if (em.macd < 0) {
        days++
      }
    }
  }
  return days >= (times - (diff || 0))
}

exports.ifMacdDownTimes = ifMacdDownTimes

function ifKdjUpTimes (list, times, diff) {
  const newList = [...list]
  // 近的在前了
  newList.reverse()
  let days = 0
  if (
    (newList[0] && newList[0].kdjDiff > 0) &&
    (newList[times - 1] && newList[times - 1].kdjDiff > 0)
  ) {
    for (let i = 0; i < times; i++) {
      const em = newList[i]
      if (em.kdjDiff > 0) {
        days++
      }
    }
  }
  return days >= (times - (diff || 0))
}

exports.ifKdjUpTimes = ifKdjUpTimes

function ifFuncTimes (func, list, times, diff) {
  const newList = [...list]
  // 近的在前了
  newList.reverse()
  let days = 0
  if (
    (newList[0] && func(newList[0])) &&
    (newList[times - 1] && func(newList[times - 1]))
  ) {
    for (let i = 0; i < times; i++) {
      const em = newList[i]
      if (func(em) < 0) {
        days++
      }
    }
  }
  return days >= (times - (diff || 0))
}

exports.ifFuncTimes = ifFuncTimes

// ema持续时间
function emaKeepDays (emaList) {
  let days = 0
  // 近的在右边
  const newList = [...emaList]
  // 近的在左边
  newList.reverse()
  const now = newList[0]
  let flag = 0
  if (now.ema5 > now.ema10 && now.ema10 > now.ema20) {
    flag = 1
  }
  if (now.ema5 < now.ema10 && now.ema10 < now.ema20) {
    flag = -1
  }
  if (!flag) {
    return 0
  }
  for (let i = 0; i < newList.length; i++) {
    const em = newList[i]
    // 现在是跌的
    if (flag === -1) {
      if (em.ema5 < em.ema10 && em.ema10 < em.ema20) {
        days++
      } else {
        return days
      }
    }
    // 现在是涨的
    if (flag === 1) {
      if (em.ema5 > em.ema10 && em.ema10 > em.ema20) {
        days++
      } else {
        return days
      }
    }
  }
  return days
}

exports.emaKeepDays = emaKeepDays

// ema持续时间
function b510t20KeepDays (asInfo) {
  let days = 0
  for (let i = 0; i < asInfo.length; i++) {
    const em = asInfo[i]
    if (em.ema5 < em.ema20 && em.ema10 < em.ema20) {
      days++
    } else {
      return days
    }
  }
  return days
}
exports.b510t20KeepDays = b510t20KeepDays

function t510b20KeepDays (asInfo) {
  let days = 0
  for (let i = 0; i < asInfo.length; i++) {
    const em = asInfo[i]
    if (em.ema5 > em.ema20 && em.ema10 > em.ema20) {
      days++
    } else {
      return days
    }
  }
  return days
}
exports.t510b20KeepDays = t510b20KeepDays

function t5b10KeepDays (asInfo) {
  let days = 0
  for (let i = 0; i < asInfo.length; i++) {
    const em = asInfo[i]
    if (em.ema5 > em.ema10) {
      days++
    } else {
      return days
    }
  }
  return days
}
exports.t5b10KeepDays = t5b10KeepDays

function t10b5KeepDays (asInfo) {
  let days = 0
  for (let i = 0; i < asInfo.length; i++) {
    const em = asInfo[i]
    if (em.ema5 < em.ema10) {
      days++
    } else {
      return days
    }
  }
  return days
}
exports.t10b5KeepDays = t10b5KeepDays

function t5b20KeepDays (asInfo) {
  let days = 0
  for (let i = 0; i < asInfo.length; i++) {
    const em = asInfo[i]
    if (em.ema5 > em.ema20) {
      days++
    } else {
      return days
    }
  }
  return days
}
exports.t5b20KeepDays = t5b20KeepDays

function t20b5KeepDays (asInfo) {
  let days = 0
  for (let i = 0; i < asInfo.length; i++) {
    const em = asInfo[i]
    if (em.ema5 < em.ema20) {
      days++
    } else {
      return days
    }
  }
  return days
}
exports.t20b5KeepDays = t20b5KeepDays

function t10b20KeepDays (asInfo) {
  let days = 0
  for (let i = 0; i < asInfo.length; i++) {
    const em = asInfo[i]
    if (em.ema10 > em.ema20) {
      days++
    } else {
      return days
    }
  }
  return days
}
exports.t10b20KeepDays = t10b20KeepDays

function t20b10KeepDays (asInfo) {
  let days = 0
  for (let i = 0; i < asInfo.length; i++) {
    const em = asInfo[i]
    if (em.ema10 < em.ema20) {
      days++
    } else {
      return days
    }
  }
  return days
}
exports.t20b10KeepDays = t20b10KeepDays

function isKdjIncrease (asInfo, index) {
  index = index || 0
  const now = asInfo[index] || {}
  const last = asInfo[index + 1] || {}
  const nowKdj = now.kdj
  const lastKdj = last.kdj
  if (nowKdj && lastKdj) {
    return nowKdj.J > lastKdj.J
  }
  return false
}
exports.isKdjIncrease = isKdjIncrease

function isKdjDecline (asInfo, index) {
  index = index || 0
  const now = asInfo[index] || {}
  const last = asInfo[index + 1] || {}
  const nowKdj = now.kdj
  const lastKdj = last.kdj
  if (nowKdj && lastKdj) {
    return nowKdj.J < lastKdj.J
  }
  return false
}
exports.isKdjDecline = isKdjDecline

function isMacdIncrease (asInfo, index) {
  index = index || 0
  const now = asInfo[index] || {}
  const last = asInfo[index + 1] || {}
  return now.macd > last.macd
}
exports.isMacdIncrease = isMacdIncrease

function isMacdDecline (asInfo, index) {
  index = index || 0
  const now = asInfo[index] || {}
  const last = asInfo[index + 1] || {}
  return now.macd < last.macd
}

exports.isMacdDecline = isMacdDecline

function isEmIncrease (asInfo, key, index) {
  index = index || 0
  const now = asInfo[index] || {}
  const last = asInfo[index + 1] || {}
  return now[key] > last[key]
}
exports.isEmIncrease = isEmIncrease

function isEmDecline (asInfo, key, index) {
  index = index || 0
  const now = asInfo[index] || {}
  const last = asInfo[index + 1] || {}
  return now[key] < last[key]
}

exports.isEmDecline = isEmDecline

function isDownLikeL (btbItem, em) {
  if (em.macd > 0 && btbItem.macdud > 8) {
    if (btbItem.b510t20KeepDays > 20) {
      if (em.sg < 1) {
        return true
      }
      if ((Math.abs(em.diff510) * 1.6) < Math.abs(em.diff1020)) {
        return true
      }
    }
  }
  return false
}
exports.isDownLikeL = isDownLikeL

function formatEmaInfo (info, key) {
  info = info || {}
  if (info.kdj) {
    info.kdjDiff = info.kdj.J - info.kdj.D
  } else {
    info.kdjDiff = 0
  }
  info.ema510DiffAbs = Math.abs(numberUtil.countDifferenceRate(info.ema5, info.ema10))
  if (key === 'dayEmaInfo') {
    // 给设置为下
    // 一般这个时候就是要转为下跌了
    if (info.macd > 0 && info.macdKeepDays >= 3 && info.kdjDiff < 0 && info.isMacdDecline) {
      const mcRate = info.macd / info.close
      if (mcRate <= 0.004) {
        info.macd = -1
        info.macdLikeDown = true
      }
    }
  }
  // 如果是5-10-20那这种时候kdj的转向意义就不大了，还是macd的转向更有用
  if (info.isKdjDecline) {
    if (info.ema5 > info.ema10 && info.ema10 > info.ema20) {
      if (info.macd > 0 && info.isMacdIncrease && info.isEm5Increase) {
        info.isKdjDecline = false
      }
    }
  }
  if (info.isKdjIncrease) {
    if (info.ema5 < info.ema10 && info.ema10 < info.ema20) {
      if (info.macd < 0 && info.isMacdDecline && info.isEm5Decline) {
        info.isKdjIncrease = false
      }
    }
  }
  return info
}

exports.formatEmaInfo = formatEmaInfo

// 重置，过滤一些欺骗性很强的信号
function resetEmaInfo (btbItem, config) {
  const dayEmaInfo = btbItem.dayEmaInfo
  const hourEmaInfo = btbItem.hourEmaInfo
  const hour4EmaInfo = btbItem.hour4EmaInfo
  const minute15EmaInfo = btbItem.minute15EmaInfo
  if (config.isStartOfHour) {
    if (
      hourEmaInfo.macd < 0 &&
      hourEmaInfo.kdjDiff < 0 &&
      (hourEmaInfo.ema5 < hourEmaInfo.ema10 && hourEmaInfo.ema10 < hourEmaInfo.ema20) &&
      (hourEmaInfo.isEm5Decline && hourEmaInfo.isEm10Decline && hourEmaInfo.isEm20Decline) &&
      hourEmaInfo.macddd > 10
    ) {
      if (
        hour4EmaInfo.macd < 0 &&
        hour4EmaInfo.kdjDiff < 0 &&
        (hour4EmaInfo.isEm5Decline && hour4EmaInfo.isEm10Decline && hour4EmaInfo.isEm20Decline)
      ) {
        if (
          minute15EmaInfo.macd < 0 &&
          (minute15EmaInfo.ema5 < minute15EmaInfo.ema10 && minute15EmaInfo.ema10 < minute15EmaInfo.ema20) &&
          (minute15EmaInfo.isEm5Decline && minute15EmaInfo.isEm10Decline && minute15EmaInfo.isEm20Decline)
        ) {
          hourEmaInfo.isMacdIncrease = false
          hourEmaInfo.isKdjIncrease = false
        }
      }
    }
    if (
      hourEmaInfo.macd > 0 &&
      hourEmaInfo.kdjDiff > 0 &&
      (hourEmaInfo.ema5 > hourEmaInfo.ema10 && hourEmaInfo.ema10 > hourEmaInfo.ema20) &&
      (hourEmaInfo.isEm5Increase && hourEmaInfo.isEm10Increase && hourEmaInfo.isEm20Increase) &&
      hourEmaInfo.macddd > 10
    ) {
      if (
        hour4EmaInfo.macd > 0 &&
        hour4EmaInfo.kdjDiff > 0 &&
        (hour4EmaInfo.isEm5Increase && hour4EmaInfo.isEm10Increase && hour4EmaInfo.isEm20Increase)
      ) {
        if (
          minute15EmaInfo.macd > 0 &&
          (minute15EmaInfo.ema5 > minute15EmaInfo.ema10 && minute15EmaInfo.ema10 > minute15EmaInfo.ema20) &&
          (minute15EmaInfo.isEm5Increase && minute15EmaInfo.isEm10Increase && minute15EmaInfo.isEm20Increase)
        ) {
          hourEmaInfo.isMacdDecline = false
          hourEmaInfo.isKdjDecline = false
        }
      }
    }
    if (
      hourEmaInfo.macd > 0 && hourEmaInfo.macdud === 1 &&
      (dayEmaInfo.kdjDiff < 0 || hour4EmaInfo.kdjDiff < 0)
    ) {
      hourEmaInfo.macd = -1 * hourEmaInfo.macd
    }
    if (
      hourEmaInfo.macd < 0 && hourEmaInfo.macddd === 1 &&
      (dayEmaInfo.kdjDiff > 0 || hour4EmaInfo.kdjDiff > 0)
    ) {
      hourEmaInfo.macd = -1 * hourEmaInfo.macd
    }
    if (
      hourEmaInfo.kdjDiff > 0 && hourEmaInfo.kdjud === 1 &&
      (dayEmaInfo.kdjDiff < 0 || hour4EmaInfo.kdjDiff < 0)
    ) {
      hourEmaInfo.kdjDiff = -1 * hourEmaInfo.kdjDiff
    }
    if (
      hourEmaInfo.kdjDiff < 0 && hourEmaInfo.kdjdd === 1 &&
      (dayEmaInfo.kdjDiff > 0 || hour4EmaInfo.kdjDiff > 0)
    ) {
      hourEmaInfo.kdjDiff = -1 * hourEmaInfo.kdjDiff
    }
  }
}

exports.resetEmaInfo = resetEmaInfo

function getDaysNetChangeRatio (asInfo, days) {
  if (!asInfo[0]) {
    return 0
  }
  let eClose = asInfo[0].close
  let sOpen = 0
  for (let i = 0; i < days; i++) {
    const em = asInfo[i]
    if (em) {
      sOpen = em.open
    } else {
      return numberUtil.countDifferenceRate(eClose, sOpen)
    }
  }
  return numberUtil.countDifferenceRate(eClose, sOpen)
}
exports.getDaysNetChangeRatio = getDaysNetChangeRatio

function getDaysRealWave (asInfo, days) {
  if (!asInfo[0]) {
    return 0
  }
  const daysNetChangeRatio = getDaysNetChangeRatio(asInfo, days)
  let sum = 0
  for (let i = 0; i < days; i++) {
    const em = asInfo[i]
    if (em) {
      sum += Math.abs(em.netChangeRatio)
    }
  }
  return Math.abs(daysNetChangeRatio / sum)
}
exports.getDaysRealWave = getDaysRealWave

function getDaysMaxWave (asInfo, days) {
  if (!asInfo[0]) {
    return 0
  }
  const daysNetChangeRatio = getDaysNetChangeRatio(asInfo, days)
  let sum = 0
  for (let i = 0; i < days; i++) {
    const em = asInfo[i]
    if (em) {
      sum += Math.abs(em.maxNetChangeRatio)
    }
  }
  return Math.abs(daysNetChangeRatio / sum)
}
exports.getDaysMaxWave = getDaysMaxWave

function days2RealMaxWave (asInfo, days) {
  if (!asInfo[0]) {
    return 0
  }
  let real = 0
  let sum = 0
  for (let i = 0; i < days; i++) {
    const em = asInfo[i]
    if (em) {
      real += Math.abs(em.netChangeRatio)
      sum += Math.abs(em.maxNetChangeRatio)
    }
  }
  return Math.abs(real / sum)
}
exports.days2RealMaxWave = days2RealMaxWave

function getNowChangeRatio (asInfo, days) {
  if (!asInfo[0]) {
    return 0
  }
  let sum = 0
  for (let i = 0; i < days; i++) {
    const em = asInfo[i]
    if (em) {
      sum += Math.abs(em.netChangeRatio)
    }
  }
  return Math.abs(asInfo[0].netChangeRatio / sum)
}
exports.getNowChangeRatio = getNowChangeRatio

function emaIncreaseDeclineKeepDays (asInfo, key) {
  let days = 0
  for (let i = 0; i < asInfo.length; i++) {
    const em = asInfo[i]
    if (em[key]) {
      days++
    } else {
      return days
    }
  }
  return days
}
exports.emaIncreaseDeclineKeepDays = emaIncreaseDeclineKeepDays

function isEmaInfoBuffer (emaInfo) {
  emaInfo = emaInfo || {}
  const diff510 = Math.abs(emaInfo.diff510)
  const diff1020 = Math.abs(emaInfo.diff1020)
  if (
    (emaInfo.ema10 > emaInfo.ema20 && emaInfo.ema5 > emaInfo.ema10) &&
    emaInfo.isMacdDecline &&
    emaInfo.kdjDiff < 0 &&
    diff1020 > (diff510 * 2)
  ) {
    return true
  }
  if (
    (emaInfo.ema10 < emaInfo.ema20 && emaInfo.ema5 < emaInfo.ema10) &&
    emaInfo.isMacdIncrease &&
    emaInfo.kdjDiff > 0 &&
    diff1020 > (diff510 * 2)
  ) {
    return true
  }
  return false
}
exports.isEmaInfoBuffer = isEmaInfoBuffer

// 盘整
function isEmaInfoReadjust (emaInfo) {
  emaInfo = emaInfo || {}
  // 下跌盘整
  if (
    emaInfo.macd > 0 &&
    (emaInfo.ema10 < emaInfo.ema20 && emaInfo.ema5 < emaInfo.ema10)
  ) {
    return true
  }
  if (
    emaInfo.macd > 0 &&
    (emaInfo.ema10 < emaInfo.ema20 && emaInfo.ema5 > emaInfo.ema10 && emaInfo.ema5 < emaInfo.ema20)
  ) {
    return true
  }
  if (
    emaInfo.macd > 0 &&
    (emaInfo.ema10 < emaInfo.ema20 && emaInfo.ema5 > emaInfo.ema10 && emaInfo.ema5 > emaInfo.ema20)
  ) {
    return true
  }
  // 上涨盘整
  if (
    emaInfo.macd < 0 &&
    (emaInfo.ema10 > emaInfo.ema20 && emaInfo.ema5 > emaInfo.ema10)
  ) {
    return true
  }
  if (
    emaInfo.macd < 0 &&
    (emaInfo.ema10 > emaInfo.ema20 && emaInfo.ema5 < emaInfo.ema10 && emaInfo.ema5 > emaInfo.ema20)
  ) {
    return true
  }
  if (
    emaInfo.macd < 0 &&
    (emaInfo.ema10 > emaInfo.ema20 && emaInfo.ema5 < emaInfo.ema10 && emaInfo.ema5 < emaInfo.ema20)
  ) {
    return true
  }
  return false
}

exports.isEmaInfoReadjust = isEmaInfoReadjust

function isEmaInfoAllIncrease (emaInfo) {
  emaInfo = emaInfo || {}
  return emaInfo.isMacdIncrease && emaInfo.isKdjIncrease && emaInfo.isEm5Increase && emaInfo.isEm10Increase && emaInfo.isEm20Increase
}

exports.isEmaInfoAllIncrease = isEmaInfoAllIncrease

function isEmaInfoAllDecline (emaInfo) {
  emaInfo = emaInfo || {}
  return emaInfo.isMacdDecline && emaInfo.isKdjDecline && emaInfo.isEm5Decline && emaInfo.isEm10Decline && emaInfo.isEm20Decline
}

exports.isEmaInfoAllDecline = isEmaInfoAllDecline

function isEmaInfoLongKong (emaInfo) {
  emaInfo = emaInfo || {}
  return (emaInfo.ema10 < emaInfo.ema20 && emaInfo.ema5 < emaInfo.ema10) &&
    emaInfo.macd < 0
}
exports.isEmaInfoLongKong = isEmaInfoLongKong

function isEmaInfoLongDuo (emaInfo) {
  emaInfo = emaInfo || {}
  return (emaInfo.ema10 > emaInfo.ema20 && emaInfo.ema5 > emaInfo.ema10) &&
    emaInfo.macd > 0
}
exports.isEmaInfoLongDuo = isEmaInfoLongDuo

function isEmaInfoDuo (emaInfo) {
  emaInfo = emaInfo || {}
  return emaInfo.kdjDiff > 0 &&
    (emaInfo.ema10 > emaInfo.ema20 && emaInfo.ema5 > emaInfo.ema10) &&
    emaInfo.macd > 0
}
exports.isEmaInfoDuo = isEmaInfoDuo

function isEmaInfoKong (emaInfo) {
  emaInfo = emaInfo || {}
  return emaInfo.kdjDiff < 0 &&
    (emaInfo.ema10 < emaInfo.ema20 && emaInfo.ema5 < emaInfo.ema10) &&
    emaInfo.macd < 0
}
exports.isEmaInfoKong = isEmaInfoKong

function isCrimpLine (emaInfo, key) {
  emaInfo = emaInfo || {}
  return emaInfo.high > emaInfo[key] && emaInfo.low < emaInfo[key] && (
    (emaInfo.open > emaInfo[key] && emaInfo.close < emaInfo[key]) ||
    (emaInfo.close > emaInfo[key] && emaInfo.open < emaInfo[key])
  )
}
exports.isCrimpLine = isCrimpLine

function canUseMaxPosition (config) {
  config = config || {}
  config.daySg = config.daySg || 15
  config.dayEmaud = config.dayEmaud || 10
  config.dayMacdud = config.dayMacdud || 10
  config.hour4Sg = config.hour4Sg || 6.5
  config.hour4Emaud = config.hour4Emaud || 10
  config.hour4Macdud = config.hour4Macdud || 10
  const dayEmaInfo = config.btbItem.dayEmaInfo || {}
  const hour4EmaInfo = config.btbItem.hour4EmaInfo || {}
  if (dayEmaInfo.sg && dayEmaInfo.sg >= config.daySg) {
    if (
      (dayEmaInfo.ema10 > dayEmaInfo.ema20 && dayEmaInfo.ema5 > dayEmaInfo.ema10) &&
      dayEmaInfo.kdjDiff > 0 &&
      dayEmaInfo.macd > 0 &&
      dayEmaInfo.macdud > config.dayMacdud &&
     ifFuncTimes((em) => {
       return em.ema5 > em.ema20 && em.ema10 > em.ema20
     }, dayEmaInfo.emInfoList || [], config.dayEmaud)
    ) {
      if (
        hour4EmaInfo.sg > config.hour4Sg &&
        (hour4EmaInfo.ema10 > hour4EmaInfo.ema20 && hour4EmaInfo.ema5 > hour4EmaInfo.ema10) &&
        hour4EmaInfo.kdjDiff > 0 &&
        hour4EmaInfo.macd > 0 &&
        hour4EmaInfo.macdud > config.hour4Macdud &&
        ifFuncTimes((em) => {
          return em.ema5 > em.ema20 && em.ema10 > em.ema20
        }, hour4EmaInfo.emInfoList || [], config.hour4Emaud)
      ) {
        return true
      }
    }
  }
  return false
}
exports.canUseMaxPosition = canUseMaxPosition

function emaInfoScoring (config) {
  // 最高6分
  const emaInfo = config.emaInfo || {}
  let count = 0
  if (emaInfo.ema10 > emaInfo.ema20 && emaInfo.ema5 > emaInfo.ema20) {
    count++
    if (
      ifFuncTimes((em) => {
        return em.ema5 > em.ema20 && em.ema10 > em.ema20
      }, emaInfo.emInfoList || [], 10)
    ) {
      count++
    }
    if (emaInfo.macd > 0) {
      count++
      if (emaInfo.macdud > 10) {
        count++
      }
    } else {
      count--
      if (emaInfo.macddd > 10) {
        count--
      }
    }
    if (emaInfo.kdjDiff > 0) {
      count++
      if (emaInfo.kdjud > 3) {
        count++
      }
    } else {
      count--
      if (emaInfo.kdjdd > 3) {
        count--
      }
    }
  } else if (emaInfo.ema10 < emaInfo.ema20 && emaInfo.ema5 < emaInfo.ema20) {
    count--
    if (
      ifFuncTimes((em) => {
        return em.ema5 < em.ema20 && em.ema10 < em.ema20
      }, emaInfo.emInfoList || [], 10)
    ) {
      count--
    }
    if (emaInfo.macd > 0) {
      count++
      if (emaInfo.macdud > 10) {
        count++
      }
    } else {
      count--
      if (emaInfo.macddd > 10) {
        count--
      }
    }
    if (emaInfo.kdjDiff > 0) {
      count++
      if (emaInfo.kdjud > 3) {
        count++
      }
    } else {
      count--
      if (emaInfo.kdjdd > 3) {
        count--
      }
    }
  }
  return count
}
exports.emaInfoScoring = emaInfoScoring

function countProportionDiff (config) {
  const btbItem = config.btbItem || {}
  const dayEmaInfo = btbItem.dayEmaInfo || {}
  const hour4EmaInfo = btbItem.hour4EmaInfo || {}
  const hourEmaInfo = btbItem.hourEmaInfo || {}
  const minute15EmaInfo = btbItem.minute15EmaInfo || {}
  if (
    (
      (minute15EmaInfo.macd > 0 && minute15EmaInfo.macdud <= 3) ||
      (minute15EmaInfo.kdjDiff > 0 && minute15EmaInfo.kdjud <= 3)
    ) &&
    (
      (hourEmaInfo.macd > 0 && hourEmaInfo.macdud <= 3) ||
      (hourEmaInfo.kdjDiff > 0 && hourEmaInfo.kdjud <= 3)
    ) &&
    (
      (hour4EmaInfo.macd > 0 && hour4EmaInfo.macdud <= 3) ||
      (hour4EmaInfo.kdjDiff > 0 && hour4EmaInfo.kdjud <= 3)
    )
  ) {
    return 0
  }
  if (dayEmaInfo.sg > 8 && hour4EmaInfo.sg > 4 && hourEmaInfo.sg > 2) {
    const dayScore = emaInfoScoring({
      emaInfo: dayEmaInfo
    })
    const hour4Score = emaInfoScoring({
      emaInfo: hour4EmaInfo
    })
    const hourScore = emaInfoScoring({
      emaInfo: hourEmaInfo
    })
    if (dayScore === 0 || hour4Score === 0 || hourScore === 0) {
      return 0
    }
    return Math.abs((dayScore + hour4Score + hourScore)) / 18
  }
  return 0
}
exports.countProportionDiff = countProportionDiff

exports.getFormatTradeTime = (val, type) => {
  type = type || '15m'
  if (type === '15m') {
    const m = moment(val).format('mm')
    if (m <= '02') {
      return moment(val).format('YYYY-MM-DD HH:00')
    }
    if (m <= '17' && m > '02') {
      return moment(val).format('YYYY-MM-DD HH:15')
    }
    if (m <= '37') {
      return moment(val).format('YYYY-MM-DD HH:30')
    }
    if (m <= '47') {
      return moment(val).format('YYYY-MM-DD HH:45')
    }
    return moment(val).add(1, 'hours').format('YYYY-MM-DD HH:00')
  }
}

const get15mTradeTimeCycle = () => {
  const m = moment().format('mm')
  if (m <= '02') {
    return 4
  }
  if (m <= '17' && m > '02') {
    return 1
  }
  if (m <= '37') {
    return 2
  }
  if (m <= '47') {
    return 3
  }
  return 4
}
exports.get15mTradeTimeCycle = get15mTradeTimeCycle

exports.getTradeTimeHm = () => {
  const h = moment().format('HH')
  const m = get15mTradeTimeCycle()
  const mStr = ['00', '15', '30', '45', '00']
  return `${h}:${mStr[m]}`
}

exports.countIfMacdDownTimes = (analysisInfoList, days, times) => {
  if (days > analysisInfoList.length) {
    days = analysisInfoList.length
  }
  let count = 0
  for (let i = 0; i < days; i++) {
    const item = analysisInfoList[i] || {}
    if (item.macd < 0) {
      count++
    }
  }
  return count >= times
}

exports.countIf5W10A20Times = (analysisInfoList, days, times) => {
  if (days > analysisInfoList.length) {
    days = analysisInfoList.length
  }
  let count = 0
  for (let i = 0; i < days; i++) {
    const item = analysisInfoList[i] || {}
    if (item.ema5 > item.ema20 && item.ema10 > item.ema20) {
      count++
    }
  }
  return count >= times
}

exports.countIf5W10B20Times = (analysisInfoList, days, times) => {
  if (days > analysisInfoList.length) {
    days = analysisInfoList.length
  }
  let count = 0
  for (let i = 0; i < days; i++) {
    const item = analysisInfoList[i] || {}
    if (item.ema5 < item.ema20 && item.ema10 < item.ema20) {
      count++
    }
  }
  return count >= times
}

exports.countLowNetChangeTimes = (analysisInfoList, days) => {
  if (days > analysisInfoList.length) {
    days = analysisInfoList.length
  }
  let count = 0
  for (let i = 0; i < days; i++) {
    const item = analysisInfoList[i] || {}
    if (Math.abs(item.netChangeRatio) < 0.3) {
      count++
    }
  }
  return count
}

exports.countKdjDownTimes = (analysisInfoList, days) => {
  if (days > analysisInfoList.length) {
    days = analysisInfoList.length
  }
  let count = 0
  for (let i = 0; i < days; i++) {
    const item = analysisInfoList[i] || {}
    if (item.kdjDiff < 0) {
      count++
    }
  }
  return count
}

exports.countIfMacdUpTimes = (analysisInfoList, days, times) => {
  if (days > analysisInfoList.length) {
    days = analysisInfoList.length
  }
  let count = 0
  for (let i = 0; i < days; i++) {
    const item = analysisInfoList[i] || {}
    if (item.macd > 0) {
      count++
    }
  }
  return count >= times
}

exports.getRecentDaysMaxRealWave = (analysisInfoList, days) => {
  days = days || 10
  if (days > analysisInfoList.length) {
    days = analysisInfoList.length
  }
  let sum = 0
  let count = 0
  let high = 0
  let low = analysisInfoList[0].open
  for (let i = 0; i < days; i++) {
    const item = analysisInfoList[i] || {}
    if (item.open > high) {
      high = item.open
    }
    if (item.close > high) {
      high = item.close
    }
    if (item.open < low) {
      low = item.open
    }
    if (item.close < low) {
      low = item.close
    }
  }
  return numberUtil.keepFourDecimals(sum / count)
}

exports.getBeforeRecentDaysAvRealWave = (analysisInfoList, days) => {
  days = days || 10
  if (days > analysisInfoList.length) {
    days = analysisInfoList.length
  }
  let sum = 0
  let count = 0
  for (let i = 1; i < (days + 1); i++) {
    const item = analysisInfoList[i] || {}
    sum += Math.abs(item.netChangeRatio)
    count++
  }
  return numberUtil.keepFourDecimals(sum / count)
}

exports.getIsBeforeRecentDaysNewHigh = (analysisInfoList, days) => {
  days = days || 20
  if (days > analysisInfoList.length) {
    days = analysisInfoList.length
  }
  let high = 0
  let index = 0
  for (let i = 0; i < days; i++) {
    const item = analysisInfoList[i] || {}
    if (item.high > high) {
      high = item.high
      index = i
    }
  }
  return index === 0
}

exports.getIsBeforeRecentDaysNewLow = (analysisInfoList, days) => {
  days = days || 20
  if (days > analysisInfoList.length) {
    days = analysisInfoList.length
  }
  let low = -1
  let index = 0
  for (let i = 0; i < days; i++) {
    const item = analysisInfoList[i] || {}
    if (low === -1 || item.low < low) {
      low = item.low
      index = i
    }
  }
  return index === 0
}

exports.getBeforeInfoRecentDaysNewHighLow = (analysisInfoList, days) => {
  const info = {
    high: 0,
    highIndex: 0,
    low: 0,
    lowIndex: 0,
    maxClose: 0,
    maxCloseIndex: 0,
    minClose: 0,
    minCloseIndex: 0
  }
  for (let index = 0; index < days; index++) {
    const v = analysisInfoList[index]
    if (!v) {
      return info
    }
    if (v.high > info.high) {
      info.high = v.high
      info.highIndex = index
    }
    if (!info.low || v.low < info.low) {
      info.low = v.low
      info.lowIndex = index
    }
    if (v.close > info.maxClose) {
      info.maxClose = v.close
      info.maxCloseIndex = index
    }
    if (!info.minClose || v.close < info.minClose) {
      info.minClose = v.close
      info.minCloseIndex = index
    }
  }
  return info
}

exports.getBeforeRecentDaysAvMaxWave = (analysisInfoList, days) => {
  days = days || 10
  if (days > analysisInfoList.length) {
    days = analysisInfoList.length
  }
  let sum = 0
  let count = 0
  for (let i = 1; i < (days + 1); i++) {
    const item = analysisInfoList[i] || {}
    if (item) {
      sum += item.highLowRate
      count++
    }
  }
  return numberUtil.keepFourDecimals(sum / count)
}
exports.getBeforeRecentDaysNeedleLineTimes = (analysisInfoList, days) => {
  days = days || 30
  if (days > analysisInfoList.length) {
    days = analysisInfoList.length
  }
  let count = 0
  for (let i = 0; i < days; i++) {
    const item = analysisInfoList[i] || {}
    if (item && (Math.abs(item.netChangeRatio) < (0.35 * item.highLowRate))) {
      if (item.highLowRate > 0.2) {
        count++
      }
    }
  }
  return count
}
exports.isRecentNeedleLine = (analysisInfoList, days) => {
  days = days || 5
  if (days > analysisInfoList.length) {
    days = analysisInfoList.length
  }
  let flag = true
  for (let i = 0; i < days; i++) {
    const item = analysisInfoList[i] || {}
    if (!(Math.abs(item.netChangeRatio) < 0.35 * item.highLowRate)) {
      flag = false
    }
  }
  return flag
}
exports.isNowRiseHighAndFall = (analysisInfoList) => {
  if (analysisInfoList.length < 21) {
    return false
  }
  const nowKline = analysisInfoList[0]
  let rate = 0
  let count = 0
  for (let i = 1; i < 21; i++) {
    const item = analysisInfoList[i] || {}
    rate += item.highLowRate || 0
    count++
  }
  if (nowKline.highLowRate > 4 * (rate / count)) {
    if (nowKline.closeLowRate <= 0.55 * nowKline.highLowRate) {
      return true
    }
  }
  return false
}
exports.getNetChangeRatioDownDaysInRange = (analysisInfoList, rangeDays) => {
  let days = 0
  let rate = 0
  for (let i = 0; i < rangeDays; i++) {
    const item = analysisInfoList[i]
    if (!item) {
      break
    }
    if (item.netChangeRatio < 0) {
      days++
      rate += item.netChangeRatio
    }
  }
  return {
    days,
    rate,
    rateAv: numberUtil.keepFourDecimals(rate / days)
  }
}
exports.getNetChangeRatioUpDaysInRange = (analysisInfoList, rangeDays) => {
  let days = 0
  let rate = 0
  for (let i = 0; i < rangeDays; i++) {
    const item = analysisInfoList[i]
    if (!item) {
      break
    }
    if (item.netChangeRatio > 0) {
      days++
      rate += item.netChangeRatio
    }
  }
  return {
    days,
    rate,
    rateAv: numberUtil.keepFourDecimals(rate / days)
  }
}

exports.getMacdUpDaysInRange = (analysisInfoList, rangeDays) => {
  let days = 0
  let rate = 0
  for (let i = 0; i < rangeDays; i++) {
    const item = analysisInfoList[i]
    if (!item) {
      break
    }
    if (item.macd > 0) {
      days++
      rate += item.netChangeRatio
    }
  }
  return {
    days,
    rate,
    rateAv: numberUtil.keepFourDecimals(rate / days)
  }
}

exports.getMacdDownDaysInRange = (analysisInfoList, rangeDays) => {
  let days = 0
  let rate = 0
  for (let i = 0; i < rangeDays; i++) {
    const item = analysisInfoList[i]
    if (!item) {
      break
    }
    if (item.macd < 0) {
      days++
      rate += item.netChangeRatio
    }
  }
  return {
    days,
    rate,
    rateAv: numberUtil.keepFourDecimals(rate / days)
  }
}
// 冲高回落
exports.getIfRiseAndFall = (info, rate) => {
  rate = rate || 20
  if (info.highLowRate >= rate && info.closeLowRate < (info.highLowRate * 0.36)) {
    if (info.highOpenRate >= (rate * 0.75)) {
      return true
    }
  }
  return false
}

exports.getClearIndexConfigParams = () => {
  return {
    now_position_usdt: 0,
    now_position_amt: 0,
    now_position_cost_price: 0,
    stop_profit_price: 0,
    stop_profit_rate: 0,
    stop_profit_order_id: '',
    buy_sell_analysis_result: {},
    ping_next_k: 0,
    ping_next_1hk: 0,
    add_times: 0,
    max_all15m_times: 0,
    direction: '',
    direction_level: 0,
    buy_sell_reason: '',
    keep_days: 0,
    market_sell_order_id: '',
    market_buy_order_id: '',
    strategy: '',
    max_income_rate: 0,
    reason_list: [],
    track_list: [],
    error_track: [],
    price_change_rank: 0
  }
}

exports.getIfOnlyDuo = (asCount, countModel1hInfo, countModel15mInfo) => {
  let onlyDuo = (
    (countModel1hInfo.count5W10A20 > (asCount * 0.82)) ||
    (countModel1hInfo.count5A10A20 > (asCount * 0.75))
  ) && (
    (countModel15mInfo.count5W10A20 > (asCount * 0.82)) ||
    (countModel15mInfo.count5A10A20 > (asCount * 0.75))
  ) && (countModel15mInfo.countMacdUp > (asCount * 0.7)) &&
    (countModel1hInfo.countMacdUp > (asCount * 0.7))
  return onlyDuo
}

exports.getIfOnlyKong = (asCount, countModel1hInfo, countModel15mInfo) => {
  let onlyKong = (
    (countModel1hInfo.count5W10B20 > (asCount * 0.82)) ||
    (countModel1hInfo.count5B10B20 > (asCount * 0.75))
  ) && (
    (countModel15mInfo.count5W10B20 > (asCount * 0.82)) ||
    (countModel15mInfo.count5B10B20 > (asCount * 0.75))
  ) && (countModel15mInfo.countMacdDown > (asCount * 0.7)) &&
    (countModel1hInfo.countMacdDown > (asCount * 0.7))
  return onlyKong
}

exports.getIfLikeDuo = (asCount, countModel1hInfo, countModel15mInfo) => {
  let flag = false
  if (
    (countModel1hInfo.count5W10A20 > (asCount * 0.6)) &&
    (countModel1hInfo.countMacdUp > (asCount * 0.7))
  ) {
    if (
      (countModel15mInfo.count5W10A20 > (asCount * 0.6)) &&
      (countModel15mInfo.countMacdUp > (asCount * 0.6))
    ) {
      flag = true
    }
  }
  if (
    (countModel1hInfo.count5W10A20 > (asCount * 0.82)) &&
    (countModel1hInfo.count5A10A20 > (asCount * 0.75)) &&
    (countModel1hInfo.countMacdUp > (asCount * 0.7))
  ) {
    flag = true
  }
  return flag
}

exports.getIfLikeKong = (asCount, countModel1hInfo, countModel15mInfo) => {
  let flag = false
  if (
    (countModel1hInfo.count5W10B20 > (asCount * 0.6)) &&
    (countModel1hInfo.countMacdDown > (asCount * 0.7))
  ) {
    if (
      (countModel15mInfo.count5W10B20 > (asCount * 0.6)) &&
      (countModel15mInfo.countMacdDown > (asCount * 0.6))
    ) {
      flag = true
    }
  }
  if (
    (countModel1hInfo.count5W10B20 > (asCount * 0.82)) &&
    (countModel1hInfo.count5B10B20 > (asCount * 0.75)) &&
    (countModel1hInfo.countMacdDown > (asCount * 0.7))
  ) {
    flag = true
  }
  return flag
}

exports.getIfAttack15m = (asCount, countModel1hInfo, countModel15mInfo) => {
  let flag = false
  if (
    (countModel15mInfo.count5W10A20 >= (asCount * 0.79)) &&
    (countModel15mInfo.countMacdUp >= (asCount * 0.79))
  ) {
    flag = true
  }
  return flag
}

exports.getIfCrash15m = (asCount, countModel1hInfo, countModel15mInfo) => {
  let flag = false
  if (
    (countModel15mInfo.count5W10B20 >= (asCount * 0.79)) &&
    (countModel15mInfo.countMacdDown >= (asCount * 0.79))
  ) {
    flag = true
  }
  return flag
}

exports.getIfDisabledBuySell = (asCount, countModel1hInfo, countModel15mInfo) => {
  let flag = false
  if (
    (countModel1hInfo.count5W10B20 >= (asCount * 0.75)) &&
    (countModel1hInfo.countMacdUp >= (asCount * 0.75))
  ) {
    flag = true
  }
  if (
    (countModel1hInfo.count5W10A20 >= (asCount * 0.75)) &&
    (countModel1hInfo.countMacdDown >= (asCount * 0.75))
  ) {
    flag = true
  }
  return flag
}

exports.getPrePositionConfig = (info) => {
  // 地量也挺好，成交小于135，数量小于160
  const countSumModelInfo = info.countSumModelInfo || {}
  let maxTrend = Math.max(countSumModelInfo.allUp, countSumModelInfo.allDown)
  let positionConfig = (maxTrend / info.asCount) / 2
  // 很奇怪现在一出现onlykong，市场就开始转向
  if (info.onlyKong || info.onlyDuo) {
    positionConfig = positionConfig + 0.1
  }
  // 混沌的阶段真的没有做的必要，
  // 经常会涨得好好的突然砸下来（莫名其妙的那种，技术指标都正常）
  // 太恶心了，本来都5个点利润了，突然一个莫名其妙的k又全部吐回去了（这种行情只能按分钟价格做）
  if (info.likeKong || info.likeKong) {
    positionConfig = positionConfig + 0.05
  }
  if (info.attack15m || info.crash15m) {
    positionConfig = positionConfig + 0.25
  }
  if (info.disabledBuySell) {
    if (positionConfig > 0.25) {
      positionConfig = 0.25
    }
  }
  if (positionConfig > 1) {
    positionConfig = 1
  }
  return numberUtil.keepTwoDecimals(positionConfig)
}

exports.checkIfMarketDownTrend = (detail) => {
  if (detail) {
    const countModel4h = detail.countModel4h || {}
    // 大级别的上攻和下跌肯定是4h和1h配合的（整个市场）
    // 日线不配合也不行
    const ifDayUp = detail.kdj1dGood ||
      detail.macd1dGood ||
      detail.ema1dGood
    // 上一波日线有0.4是5大于10的，而且macd大于0.8
    const if4hOtherDown = detail.macd4hBad ||
      detail.ema4hBad ||
      countModel4h.count5B10 >= (0.7 * detail.asCount)
    let c5B10Rate = 0.5
    if (ifDayUp && !if4hOtherDown) {
      c5B10Rate = 0.8
    }
    const if4hUp = detail.macd4hGood ||
      detail.ema4hGood
    if (
      detail.kdj4hBad &&
      !if4hUp &&
      detail.likeKong &&
      (!ifDayUp || if4hOtherDown) &&
      // ema5和ema10也得配合一下
      // 如果日线有反向的是不是得0.8
      countModel4h.count5B10 >= (c5B10Rate * detail.asCount) &&
      (detail.macd1hBad && detail.ema1hBad)
    ) {
      return true
    }
    if (detail.macd4hBad && detail.ema4hBad && detail.macd1hBad && detail.ema1hBad) {
      if ((detail.macd1dBad || detail.ema1dBad) && !detail.kdj1dGood) {
        return true
      }
    }
  }
  return false
}

exports.checkIfMarketUpTrend = (detail) => {
  if (detail) {
    const countModel4h = detail.countModel4h || {}
    // 大级别的上攻和下跌肯定是4h和1h配合的（整个市场）
    // 日线不配合也不行
    const ifDayDown = detail.kdj1dBad ||
      detail.macd1dBad ||
      detail.ema1dBad
    const if4hOtherUp = detail.macd4hGood ||
      detail.ema4hGood ||
      countModel4h.count5A10 >= (0.7 * detail.asCount)
    const if4hDown = detail.macd4hBad ||
      detail.ema4hBad
    // 不需要4h其他的过半，之前那波，4h的macd和ema开始的时候有一半多都是跌的，但是也启动了，因为他有日线macd的配合
    let c5A10Rate = 0.5
    if (ifDayDown && !if4hOtherUp) {
      c5A10Rate = 0.8
    }
    if (
      detail.kdj4hGood &&
      !if4hDown &&
      detail.likeDuo &&
      (!ifDayDown || if4hOtherUp) &&
      // ema5和ema10也得配合一下
      // 如果日线有反向的是不是得0.8
      countModel4h.count5A10 >= (c5A10Rate * detail.asCount) &&
      (detail.macd1hGood && detail.ema1hGood)
    ) {
      return true
    }
    if (detail.macd4hGood && detail.ema4hGood && detail.macd1hGood && detail.ema1hGood) {
      if ((detail.macd1dGood || detail.ema1dGood) && !detail.kdj1dBad) {
        return true
      }
    }
  }
  return false
}

exports.getAnalysisMarketInfo = (detail) => {
  const line = (0.8 * detail.asCount) || 100000
  const countModel4h = detail.countModel4h || {}
  detail.kdj4hBad = countModel4h.countKdjDown >= line
  detail.kdj4hGood = countModel4h.countKdjUp >= line
  detail.kdj4hNormal = !(detail.kdj4hBad || detail.kdj4hGood)
  detail.macd4hBad = countModel4h.countMacdDown >= line
  detail.macd4hGood = countModel4h.countMacdUp >= line
  detail.macd4hNormal = !(detail.macd4hBad || detail.macd4hGood)
  detail.ema4hBad = countModel4h.count5W10B20 >= line
  detail.ema4hGood = countModel4h.count5W10A20 >= line
  detail.ema4hNormal = !(detail.ema4hBad || detail.ema4hGood)

  const countModel1h = detail.countModel1h || {}
  detail.kdj1hBad = countModel1h.countKdjDown >= line
  detail.kdj1hGood = countModel1h.countKdjUp >= line
  detail.kdj1hNormal = !(detail.kdj1hBad || detail.kdj1hGood)
  detail.macd1hBad = countModel1h.countMacdDown >= line
  detail.macd1hGood = countModel1h.countMacdUp >= line
  detail.macd1hNormal = !(detail.macd1hBad || detail.macd1hGood)
  detail.ema1hBad = countModel1h.count5W10B20 >= line
  detail.ema1hGood = countModel1h.count5W10A20 >= line
  detail.ema1hNormal = !(detail.ema1hBad || detail.ema1hGood)
  detail.count1h5W10A20Days = countModel1h.count5W10A20Days || 0
  detail.count1h5W10B20Days = countModel1h.count5W10B20Days || 0

  const countModel15m = detail.countModel15m || {}
  detail.kdj15mBad = countModel15m.countKdjDown >= line
  detail.kdj15mGood = countModel15m.countKdjUp >= line
  detail.kdj15mNormal = !(detail.kdj15mBad || detail.kdj15mGood)
  detail.macd15mBad = countModel15m.countMacdDown >= line
  detail.macd15mGood = countModel15m.countMacdUp >= line
  detail.macd15mNormal = !(detail.macd15mBad || detail.macd15mGood)
  detail.ema15mBad = countModel15m.count5W10B20 >= line
  detail.ema15mGood = countModel15m.count5W10A20 >= line
  detail.ema15mNormal = !(detail.ema15mBad || detail.ema15mGood)

  const countModel1d = detail.countModel1d || {}
  detail.kdj1dBad = countModel1d.countKdjDown >= line
  detail.kdj1dGood = countModel1d.countKdjUp >= line
  detail.kdj1dNormal = !(detail.kdj1dBad || detail.kdj1dGood)
  detail.macd1dBad = countModel1d.countMacdDown >= line
  detail.macd1dGood = countModel1d.countMacdUp >= line
  detail.macd1dNormal = !(detail.macd1dBad || detail.macd1dGood)
  detail.ema1dBad = countModel1d.count5W10B20 >= line
  detail.ema1dGood = countModel1d.count5W10A20 >= line
  detail.ema1dNormal = !(detail.ema1dBad || detail.ema1dGood)
  detail.marketDownTrend = this.checkIfMarketDownTrend(detail)
  detail.marketUpTrend = this.checkIfMarketUpTrend(detail)
}

const getTagNumber = (tagList) => {
  // 第一个是bad，第二个是good
  if (tagList[0]) {
    return -1
  }
  if (tagList[1]) {
    return 1
  }
  return 0
}
// 复制模式
exports.copyIntervalTag = (info) => {
  return [
    [
      getTagNumber([info.kdj1dBad, info.kdj1dGood]),
      getTagNumber([info.macd1dBad, info.macd1dGood]),
      getTagNumber([info.ema1dBad, info.ema1dGood])
    ],
    [
      getTagNumber([info.kdj4hBad, info.kdj4hGood]),
      getTagNumber([info.macd4hBad, info.macd4hGood]),
      getTagNumber([info.ema4hBad, info.ema4hGood])
    ],
    [
      getTagNumber([info.kdj1hBad, info.kdj1hGood]),
      getTagNumber([info.macd1hBad, info.macd1hGood]),
      getTagNumber([info.ema1hBad, info.ema1hGood])
    ],
    [
      getTagNumber([info.kdj15mBad, info.kdj15mGood]),
      getTagNumber([info.macd15mBad, info.macd15mGood]),
      getTagNumber([info.ema15mBad, info.ema15mGood])
    ]
  ]
}
